package com.lb.client;

import com.alibaba.fastjson.JSON;
import feign.Request;
import feign.Response;
import feign.Util;
import feign.slf4j.Slf4jLogger;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Objects;
import java.util.logging.Level;

import static com.alibaba.fastjson.serializer.SerializerFeature.WriteNullStringAsEmpty;
import static com.lb.base.constants.BaseConstants.*;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * Client Feign 请求跟踪拦截器
 *
 * @author xiemingzhi
 * @since 1.0
 */
@Slf4j
public class ClientLogFeignInterceptor extends Slf4jLogger {

    private static final String FEIGN_REQUEST = "Feign-Request = {}";
    private static final String FEIGN_RESPONSE = "Feign-Response = {}";

    public ClientLogFeignInterceptor(Class<?> clazz) {
        super(clazz);
    }

    protected void logRequest(String configKey, Level logLevel, Request request) {
        ClientLogRequest clientLogRequest = ClientLogRequest.build(configKey, request);
        clientLogRequest.setType(ClientEnum.FEIGN.getDesc());
        log.info(FEIGN_REQUEST, JSON.toJSONString(clientLogRequest, WriteNullStringAsEmpty));
    }

    protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response, long elapsedTime) throws IOException {
        ClientLogResponse clientLogResponse = new ClientLogResponse();
        clientLogResponse.setClassMethod(configKey);
        clientLogResponse.setElapsedTime(elapsedTime + MILLIS_UNIT_SUFFIX);
        clientLogResponse.setType(ClientEnum.FEIGN.getDesc());

        if (Objects.nonNull(response)) {
            clientLogResponse.setStatus(response.status());
            if (response.body() != null) {
                byte[] bodyData = Util.toByteArray(response.body().asInputStream());
                clientLogResponse.setBody(new String(bodyData, UTF_8));
                response = response.toBuilder().body(bodyData).build();
            }
        }

        log.info(FEIGN_RESPONSE, JSON.toJSONString(clientLogResponse, WriteNullStringAsEmpty));
        return super.logAndRebufferResponse(configKey, logLevel, response, elapsedTime);
    }

    protected IOException logIOException(String configKey, Level logLevel, IOException ioe, long elapsedTime) {
        ClientLogResponse clientLogResponse = new ClientLogResponse();
        clientLogResponse.setClassMethod(configKey);
        clientLogResponse.setElapsedTime(elapsedTime + MILLIS_UNIT_SUFFIX);
        clientLogResponse.setType(ClientEnum.FEIGN.getDesc());

        StringWriter sw = new StringWriter();
        ioe.printStackTrace(new PrintWriter(sw));
        clientLogResponse.setBody(sw.toString());

        log.info(FEIGN_RESPONSE, JSON.toJSONString(clientLogResponse, WriteNullStringAsEmpty));
        return ioe;
    }
}
